// Copyright (C) 2010 Razvan Constantin <razvan.constantin@rconst.net>
//
// This file is part of FileBow.
//
// FileBow is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// FileBow is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FileBow.  If not, see <http://www.gnu.org/licenses/>.

#include "logic/path-scanner.h"

#include <memory>
#include <set>
#include <string>
#include <vector>

#include <glib.h>
#include <gtest/gtest.h>

#include "common/common.h"
#include "common/strings.h"
#include "logic/path-tree.h"
#include "testing/test_drive.h"

#include <Poco/File.h>
#include <Poco/Path.h>

using namespace std;
using Poco::File;
using Poco::Path;

namespace filebow {
namespace testing {

class PathScannerTest : public ::testing::Test {
  protected: static void SetUpTestCase() {
    g_thread_init(NULL);
    mTestDrive.reset(new TestDrive);
  }
  protected: static void TearDownTestCase() {
    mTestDrive.reset();
  }

  protected: void SetUp() {
    mTree.reset(new PathTree);
    mScanner.reset(new PathScanner(mTestDrive->path()));
  }
  protected: void TearDown() {
    mScanner.reset();
    mTree.reset();
  }

  protected: int CountTreeFiles(PathTree* tree = NULL) {
    if (!tree) {
      tree = mTree.get();
    }
    int count = 0;
    for (PathTree::Iterator it(tree); !it.done(); ++it) {
      count += it->type() == PathType::FILE;
    }
    return count;
  }
  protected: string DumpTree(PathTree* tree = NULL) {
    if (!tree) {
      tree = mTree.get();
    }
    string dump("mPathTree:");
    int testPathLength = mTestDrive->path().length();
    for (PathTree::Iterator it(tree); !it.done(); ++it) {
      string pathStr = mTree->GetPath(*it).toString();
      if (pathStr.length() < testPathLength) {
        continue;
      }
      dump += "\n" + pathStr.substr(testPathLength);
    }
    return dump;
  }

  protected: static auto_ptr<TestDrive> mTestDrive;
  protected: auto_ptr<PathTree> mTree;
  protected: auto_ptr<PathScanner> mScanner;
};
auto_ptr<TestDrive> PathScannerTest::mTestDrive;


TEST_F(PathScannerTest, TestScan) {
  mScanner->Scan(mTree.get());
  EXPECT_EQ(mTestDrive->size(), CountTreeFiles()) << DumpTree();
}

TEST_F(PathScannerTest, TestMaxFiles) {
  mScanner->SetMaxFiles(5);
  mScanner->Scan(mTree.get());
  EXPECT_EQ(5, CountTreeFiles()) << DumpTree();
}

TEST_F(PathScannerTest, TestMaxDepth) {
  mScanner->SetMaxDepth(2);
  mScanner->Scan(mTree.get());
  EXPECT_EQ(mTestDrive->size() - 2, CountTreeFiles()) << DumpTree();
}

TEST_F(PathScannerTest, TestNoDepth) {
  mScanner->SetMaxDepth(0);
  mScanner->Scan(mTree.get());
  EXPECT_EQ(4, CountTreeFiles()) << DumpTree();
}

TEST_F(PathScannerTest, TestExclusion) {
  mScanner->SetExclusionPatterns(Split("file121;dir13", ';'));
  mScanner->Scan(mTree.get());
  EXPECT_EQ(mTestDrive->size() - 4, CountTreeFiles()) << DumpTree();
}

TEST_F(PathScannerTest, TestAsyncScan) {
  mScanner->AsyncScan();
  mScanner->Lock();
  EXPECT_TRUE(NULL == mScanner->tree());
  mScanner->Unlock();
  mScanner->Wait();
  EXPECT_EQ(mTestDrive->size(), CountTreeFiles(mScanner->tree()))
      << DumpTree(mScanner->tree());
}

} // namespace testing
} // namespace filebow
